
// function instanceOf(obj, constructor){
//     let proto = obj._proto_
//     while(true){
//         if(proto === null){
//             return false
//         }
//         if(proto === constructor.prototype){
//             return true
//         }
//         proto = proto._proto_
//     }
// }

function instanceOf(obj,constructor){
    let proto = obj._proto_
    while(true){
        if(proto === null){
            return false
        }
        if(proto === constructor.prototype){
            return true
        }
        proto = proto._proto_
    }
}

// function New(){
//     let constructor = Array.prototype.shift.call(arguments)
//     // 创建一个空对象，并将原型设置为构造函数原型
//     let obj = Object.create(constructor.prototype)
//     // 将构造函数this指向新对象，并执行构造函数
//     let result = constructor.call(obj,arguments)
//     let flag = result && (typeof result  === 'fuction' ||  typeof result === 'object')
//     return flag ? result : obj
// }

function New(){
    let constructor = Array.prototype.shift.call(arguments)
    let obj = Object.create(constructor.prototype)
    let result = constructor.apply(obj,arguments)
    let flag = result && (typeof result === 'function' || typeof result === 'object')
    return flag ? result : obj


}

// function generatorToAsync(generatorFn) {
//     let gen = generatorFn.apply(this,arguments)
//     return function () {
//         return new Promise((resolve, reject) => {
//             function go(key,args) {
//                 let res
//                 try {
//                     res = gen[key](args)
//                 } catch (error) {
//                     reject(error)
//                 }
//                 const { value, done } = res
//                 if(done){
//                     resolve(value)
//                 } else {
//                     Promise.resolve(value).then(val => go('next', val), err => go('throw', err))
//                 }
//             }

//             go(['next'])
//         })
//     }
// }
function generatorToAsync(generatorFn){
    let gen = generatorFn.apply(this,arguments)
    return function() {
        return new Promise((resolve,reject) => {
            function go(key,args){
                let res
                try {
                    res = gen[key](args)
                } catch (error) {
                    reject(error)
                    
                }
                const { value,done } = res
                if(done){
                    resolve(value)
                } else {
                    Promise.resolve(value).then(res => go('next', res), err => go('throw',err))
                }
            }
            go('next')
        })

    }
}


function debounce(fn,wait,immediate){
    let timer = null,
    return function() {
        if(timer){
            clearTimeout(timer)
        }
        if(immediate){
            let callnow = !timer
            timer = setTimeout(() => {
                timer = null
            },wait)
            if(!callnow){
                fn.apply(this,arguments)
            }
        } else {
            timer = setTimeout(() => {
                fn.apply(this,arguments)
                timer = null
            },wait)
        }
    }
}

function throttle(fn,wait,immediate){
    let timer, current = 0
    return function(){
        if(immediate){
            let now = Date.now()
            if(now - current > wait){
                fn.apply(this,arguments)
                current = now
            }
        } else {
            if(!timer){
               timer = setTimeout(() => {
                    fn.apply(this,arguments)
                    timer = null
                    clearTimeout(timer)
               },wait)
            }
        }
    }
}


function deepClone(obj){
    if(obj == null) return  obj
    if(obj instanceof Date) return obj
    if(obj instanceof RegExp) return obj
    if(typeof obj !== 'object') return obj
    let result = obj instanceof Array ? [] : {}
    for(let key in obj){
        if(obj.hasOwnPrototype(key)){
            let value = obj[key]
            if(typeof value === 'object'){
                result = this.deepClone(value)
            } else {
                result[key] = value
            }
        }
    }
    return result
}


class EventEmitter{
    constructor(){
        this.events = {}
    }

    on(name,fn){
        if(this.events[name]){
            this.events[name].push(fn)
        } else {
            this.events[name] = [fn]
        }
    }

    off(name){
        if(this.events[name]){
            delete this.events[name]
        }
    }

    once(name,fn){
        function f(){
            fn()
            this.off(name)
        }
        this.on(name,f)
    }

    emit(name,...rest){
        if(this.events[name]){
            this.events[name].forEach((fn) => {
                fn.apply(this,...rest)
            })
        }
    }
}

function getUrlParams(url){
    if(url && url.indexOf('?') > -1){
        let arr = url.split('?')
        let str = arr[1]
        let searchArr = str.split('&')
        let result = {}
        searchArr.forEach(item => {
            let itemArr = item.split('=')
            let key = itemArr[0]
            let value = itemArr[1]
            result[key] = value
        })
        return result
    }
    return null
}

function setUrlParams(url,params){
    let str = Object.keys(params).reduce((pre,current) => {
        if(!pre){
            pre = "?" + current + "=" + params[current]
        } else {
            pre = pre + '&' + current + "=" + params[current]
        }
    },'')
    return str ? url + str : url
}

function getTreeList(list,pid){
    let treeList = list.filter(item => item.pid === pid)
    for(let item of treeList){
        let arr = list.filter(item => item.pid === item.id)
        if(arr.length){
            item.children = arr
        }
    }
    return treeList
}


Function.prototype.sx_call = function(obj,...rest){
    obj = obj || window
    const fn = Symbol()
    obj[fn] = this
    return obj[fn](...rest)
    
}

Function.prototype.sx_apply = function(obj, rest){
    obj = obj || window
    const fn = Symbol()
    obj[fn] = this
    return obj[fn](...rest)
}

Function.prototype.sx_bind = function(obj,...arg){
    obj = obj || window
    const fn = Symbol()
    obj[fn] = this
    return function(...rest){
        let params = [...arg, ...rest]
        return obj[fn](...params)
    }
}




function compose(...fn){
    if(!fn.length) return (v) => v
    if(fn.length === 1) return fn[0]
    return fn.reduce((pre,cur) => (...args) =>
        pre(cur(...args))
    )
}

function mySetTimeout(fn,wait) {
    let timer = null
    function timer(){
       timer =  setTimeout(()=> {
            fn.apply(this)
            timer()
        },wait)
    }

    timer()
    return {
        cancle: () => {
            clearTimeout(timer)
        }
    }
}



